#!/usr/bin/python
import subprocess
import sys
import os
import util
from django.core.management.base import BaseCommand, CommandError
from optparse import make_option
from package.models import Module, PackageName, Package, FixedBug, ChangedPackage, Dependancy, OSRelease, DependancyOfBuild

class Command(BaseCommand):
    option_list = BaseCommand.option_list + (
        make_option('-o',
            '--'+util.OS_RELEASE,
            action='store',
            type='string',
            dest=util.OS_RELEASE,
            help='designate the os release. eg. \'s11u2\' or \'s12\''),
        make_option('-b',
            '--'+util.BUILD,
            action='store',
            type='string',
            dest=util.BUILD,
            help='designate the build like \'04\' or \'16\''),
    )
    task = 'collect_depend'
    ips_prefix='file:///net/ipsbj.cn.oracle.com/dtrepo/'

    def clear_build(self):
        os_release,created = OSRelease.objects.get_or_create(name=self.os_release_str)
        DependancyOfBuild.objects.filter(os_release=os_release, build_no=self.build).delete()

    def get_depend_by_cmd(self, pkg):
        command = 'pkg contents -mrg {0} {1} | /usr/xpg4/bin/grep -E ^depend'.format(self.ips_url, pkg)
        stdout, stderr = util.run_bash(command)
        if stderr:
            util.error_log(self.task, 'pkg contents command fail',
                util.pkg_log_info.format(pkg, self.os_release_str, self.build)
            )
            return None
        else:
            return stdout

    def get_depend(self, pkg, depend_list_file):
        all_pkg_depend = util.read_file(depend_list_file)
        pkg_depend_list = all_pkg_depend.split('\n\n')
        for pkg_depend in pkg_depend_list:
            if pkg_depend: #if not empty
                pkg_head,pkg_depend_std = pkg_depend.split('\n', 1)
                if pkg in pkg_head:
                    return pkg_depend_std
        print '*'*10+'Package:'+pkg+' Depend Not Found'+'*'*10
        return None

    #create a pkg name in db, flag is_normal as false,
    #because pkg names from collecting depends can not found in db are abnormal
    def get_or_create_pkg_name(self, pkg):
        pkg_name_queryset = PackageName.objects.filter(name=pkg)
        if not pkg_name_queryset:
            print 'create pkg'
            return PackageName.objects.create(name=pkg, is_normal=False)
        else:
            return pkg_name_queryset[0]

    def store_depend(self, pkg, depend_pkg):
        pkg_name = self.get_or_create_pkg_name(pkg)
        depend_pkg_name = self.get_or_create_pkg_name(depend_pkg)
        os_release,created = OSRelease.objects.get_or_create(name=self.os_release_str)
        dependancy,created = Dependancy.objects.get_or_create(origin_package=pkg_name, depend_package=depend_pkg_name)
        dependofbuild,created = DependancyOfBuild.objects.get_or_create(
            relation=dependancy, os_release=os_release, build_no=self.build
        )
        if not created:
            print 'bug repeated relation {0}:{1}'.format(pkg, depend_pkg)

    def process_depends(self, pkg, pkg_depends):
        for depend in pkg_depends.splitlines():
            index = depend.index('fmri=') + 5
            depend_pkg = depend[index:].split(' ', 1)[0]
            at_index = depend_pkg.find('@')
            if at_index > -1:
                depend_pkg = depend_pkg[:at_index]
            self.store_depend(pkg, depend_pkg)

    def log_build_depend(self, pkg_list_file, depend_list_file):
        pkg_list_data = util.read_file(pkg_list_file)
        log_handle = open(depend_list_file, 'w')
        for line in pkg_list_data.split('\n'):
            if util.CATEGORY in line: #if it has category indicates it is a working package not obsoleted or renamed
                pkg_info_dict = util.get_dict_from_line(line)
                pkg_name = pkg_info_dict[util.NAME]
                log = 'pkg: {0}\n'.format(pkg_name)
                log += self.get_depend_by_cmd(pkg_name)+'\n'
                log_handle.write(log)
        log_handle.close()

    def handle(self, *args, **options):
        self.os_release_str = options[util.OS_RELEASE]
        self.build = options[util.BUILD]
        if not self.os_release_str or not self.build:
            sys.stderr.write('build or os_release option not given\n')
            util.halt(self.task)
        self.ips_url = '{0}{1}/{2}'.format(self.ips_prefix, self.os_release_str, self.build)
        pkg_list_file = util.pkg_list_file.format(self.os_release_str, self.build)
        if not os.path.isfile(pkg_list_file):
            sys.stderr.write('Error: {0} build {1} package list does not exists\n'.format(self.os_release_str, self.build))
            util.halt(self.task)
        depend_list_file = util.pkg_list_path + 'depend_{0}_b{1}.list'.format(self.os_release_str, self.build)
        if not os.path.isfile(depend_list_file): #if depend list file not found, generate it
            self.log_build_depend(pkg_list_file, depend_list_file)
        self.clear_build()
        pkg_list_data = util.read_file(pkg_list_file)
        for line in pkg_list_data.split('\n'):
            if util.CATEGORY in line: #if it has category indicates it is a working package not obsoleted or renamed
                pkg_info_dict = util.get_dict_from_line(line)
                pkg_name = pkg_info_dict[util.NAME]
                pkg_depends = self.get_depend(pkg_name, depend_list_file)
                if pkg_depends:
                    self.process_depends(pkg_name, pkg_depends)
        util.log(self.task, 'success')
